package com.yanqu.road.dao.impl.player;

import com.yanqu.road.dao.db.DbNameStrategy;
import com.yanqu.road.dao.db.DbParameter;
import com.yanqu.road.dao.impl.TempDataObjectDao;
import com.yanqu.road.entity.enums.ePlayerAttrType;
import com.yanqu.road.entity.player.UserAttribute;

import java.sql.*;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class UserAttributeDaoImpl extends TempDataObjectDao<UserAttribute> {

	public Map<ePlayerAttrType, UserAttribute> getUserAttributeMap(long userId) {
		Map<ePlayerAttrType, UserAttribute> dataMap = new ConcurrentHashMap<>();
		ResultSet rs = null;
		CallableStatement call = null;
		int tableIndex = (int) (userId % 16);
		String sql = MessageFormat.format("select * from t_u_attr_{0} where userId =?", tableIndex);
		try {
			getDb().setConnName(DbNameStrategy.getUserDb());
			call = getDb().getConnection().prepareCall(sql);
			call.setLong(1, userId);
			rs = call.executeQuery();
			while (rs.next()) {
				UserAttribute data = parse(rs);
				dataMap.put(data.getType(), data);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			getDb().closeConnection(call, rs);
		}
		return dataMap;
	}

	public UserAttribute getUserAttribute(long userId, ePlayerAttrType attrId) {
		ResultSet rs = null;
		CallableStatement call = null;

		int tableIndex = (int) (userId % 16);
		String sql = MessageFormat.format("select * from t_u_attr_{0} where userId =? and attrId=?", tableIndex);
		try {
			getDb().setConnName(DbNameStrategy.getUserDb());
			call = getDb().getConnection().prepareCall(sql);
			call.setLong(1, userId);
			call.setInt(2, attrId.getValue());
			rs = call.executeQuery();
			while (rs.next()) {
				UserAttribute data = parse(rs);
				return data;
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			getDb().closeConnection(call, rs);
		}

		return null;
	}

	@Override
	protected boolean addData(UserAttribute data) {
		PreparedStatement call = null;
		int tableIndex = (int) (data.getUserId() % 16);
		String sql = MessageFormat.format("INSERT INTO t_u_attr_{0}(userId,attrId,value,lastUpdateTime) VALUES(?,?,?,?)", tableIndex);
		try {
			getDb().setConnName(DbNameStrategy.getUserDb());
			call = getDb().getConnection().prepareStatement(sql);
			int i = 1;
			call.setLong(i++, data.getUserId());
			call.setInt(i++, data.getType().getValue());
			call.setLong(i++, data.getValue());
			call.setLong(i++, data.getLastUpdateTime());
			return call.executeUpdate() > 0;
		} catch (Exception e) {
			logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
		} finally {
			getDb().closeConnection(call, null);
		}
		return false;
	}

	@Override
	protected boolean updateData(UserAttribute data) {
		PreparedStatement call = null;
		int tableIndex = (int) (data.getUserId() % 16);
		String sql = MessageFormat.format("UPDATE t_u_attr_{0} SET value=?,lastUpdateTime=? WHERE userId=? and attrId=?", tableIndex);
		try {
			getDb().setConnName(DbNameStrategy.getUserDb());
			call = getDb().getConnection().prepareStatement(sql);
			int i = 1;
			call.setLong(i++, data.getValue());
			call.setLong(i++, data.getLastUpdateTime());
			call.setLong(i++, data.getUserId());
			call.setInt(i++, data.getType().getValue());
			return call.executeUpdate() > 0;
		} catch (Exception e) {
			logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
		} finally {
			getDb().closeConnection(call, null);
		}
		return false;
	}

	public boolean updateUserAttribute(long userId, ePlayerAttrType attrType, long value) {
		int tableIndex = (int) (userId % 16);
		String sql = MessageFormat.format("UPDATE t_u_attr_{0} SET value=?,lastUpdateTime=? WHERE userId=? and attrId=?", tableIndex);
		try{
			getDb().setConnName(DbNameStrategy.getUserDb());
			Map<Integer, DbParameter> para = new HashMap<>();
			int i = 1;
			para.put(i++, new DbParameter(Types.BIGINT, value));
			para.put(i++, new DbParameter(Types.BIGINT, System.currentTimeMillis()));
			para.put(i++, new DbParameter(Types.BIGINT, userId));
			para.put(i++, new DbParameter(Types.INTEGER, attrType.getValue()));
			return getDb().executeNoneQuery(sql, para) > -1;
		} catch (Exception e) {
			logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
		}
		return false;
	}

	public boolean updateAddUserAttribute(long userId, ePlayerAttrType attrType, long addValue) {
		int tableIndex = (int) (userId % 16);
		String sql = MessageFormat.format("UPDATE t_u_attr_{0} SET value=value + ?,lastUpdateTime=? WHERE userId=? and attrId=?", tableIndex);
		try{
			getDb().setConnName(DbNameStrategy.getUserDb());
			Map<Integer, DbParameter> para = new HashMap<>();
			int i = 1;
			para.put(i++, new DbParameter(Types.BIGINT, addValue));
			para.put(i++, new DbParameter(Types.BIGINT, System.currentTimeMillis()));
			para.put(i++, new DbParameter(Types.BIGINT, userId));
			para.put(i++, new DbParameter(Types.INTEGER, attrType.getValue()));
			return getDb().executeNoneQuery(sql, para) > -1;
		} catch (Exception e) {
			logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
		}
		return false;
	}

	public boolean updateAddHeart(long userId, ePlayerAttrType attrType, long addValue, int limitValue) {
		int tableIndex = (int) (userId % 16);
		String sql = MessageFormat.format("UPDATE t_u_attr_{0} SET value= value + ?,lastUpdateTime=? WHERE userId=? and attrId=? and value < {1}", tableIndex, limitValue);
		try{
			getDb().setConnName(DbNameStrategy.getUserDb());
			Map<Integer, DbParameter> para = new HashMap<>();
			int i = 1;
			para.put(i++, new DbParameter(Types.BIGINT, addValue));
			para.put(i++, new DbParameter(Types.BIGINT, System.currentTimeMillis()));
			para.put(i++, new DbParameter(Types.BIGINT, userId));
			para.put(i++, new DbParameter(Types.INTEGER, attrType.getValue()));
			return getDb().executeNoneQuery(sql, para) > -1;
		} catch (Exception e) {
			logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
		}
		return false;
	}

	public boolean updateLoseHeart(long userId, ePlayerAttrType attrType, long addValue, int limitValue) {
		int tableIndex = (int) (userId % 16);
		String sql = MessageFormat.format("UPDATE t_u_attr_{0} SET value= value + ?,lastUpdateTime=? WHERE userId=? and attrId=? and value > {1}", tableIndex, limitValue);
		try{
			getDb().setConnName(DbNameStrategy.getUserDb());
			Map<Integer, DbParameter> para = new HashMap<>();
			int i = 1;
			para.put(i++, new DbParameter(Types.BIGINT, addValue));
			para.put(i++, new DbParameter(Types.BIGINT, System.currentTimeMillis()));
			para.put(i++, new DbParameter(Types.BIGINT, userId));
			para.put(i++, new DbParameter(Types.INTEGER, attrType.getValue()));
			return getDb().executeNoneQuery(sql, para) > -1;
		} catch (Exception e) {
			logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
		}
		return false;
	}

	@Override
	protected UserAttribute parseData(ResultSet rs) throws SQLException {
		UserAttribute data = new UserAttribute();
		int type = rs.getInt("attrId");
		long value = rs.getLong("value");
		data.setLastUpdateTime(rs.getLong("lastUpdateTime"));
		data.setUserId(rs.getLong("userId"));
		data.setType(ePlayerAttrType.forValue(type));
		data.setValue(value);
		return data;
	}
}
